package com.pai.service;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;

import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;

import com.pai.entity.MyInfo;
import com.pai.entity.User;
import com.pai.entity.UserList;
import com.pai.gui.component.UserListModel;
import com.pai.util.PropertiesUtil;

/**
 * UDP广播服务类，用于搜寻同一子网内的用户。
 * @author Jeff
 * 
 */
public class BroadCastService {
	
	public static BroadCastService myservice = new BroadCastService();

	private int port;

	private InetAddress broadcastAddress;
	/**
	 * 构造方法，从本地的properties文件里读取到服务线程的端口
	 */
	public BroadCastService() {
		PropertiesUtil propertieUtil = new PropertiesUtil();
		propertieUtil.loadPropertyFile("src/config.properties");

		try {
			this.broadcastAddress = InetAddress.getByName("255.255.255.255");
			this.port = Integer.parseInt(propertieUtil
					.getProperty("broadcast_port"));
		} catch (NumberFormatException e) {
			throw new IllegalArgumentException("端口号设置错误，请输入整数的端口号。");
		} catch (UnknownHostException e) {
			throw new IllegalArgumentException("udp广播地址设置错误。请输入正确的(符合条件的)ip地址");
		}
	}

	// 默认全网广播 端口用配置文件的端口
	public void sendMessage(String message) {
		try {
			sendMessage(message, broadcastAddress, port);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 发送消息的方法。
	 * @param message 消息内容
	 * @param addr 地址
	 * @param myport 端口
	 * @throws IOException
	 */
	public void sendMessage(String message, InetAddress addr, int myport)
			throws IOException {
		System.out.println("send UDP  message: " + message);
		DatagramPacket sendDP = new DatagramPacket(message.getBytes(),
				message.length(), addr, myport);
		DatagramSocket clientDSocket = new DatagramSocket();
		try {
			clientDSocket.send(sendDP);
		} catch (IOException e) {
			e.printStackTrace();
		}
		clientDSocket.close();
	}

	/**
	 * 接收udp包的函数。新建线程来反复接收udp包。当收到包时增加用户(需要修改)
	 * 
	 * @param listmodel
	 *            usericonlist的数据源
	 * @throws IOException
	 */
	public void receiveMessage(final UserListModel listmodel)
			throws IOException {
		final byte[] arb = new byte[1024];
		final DatagramPacket receiveDP = new DatagramPacket(arb, arb.length);
		final DatagramSocket clientDSocket = new DatagramSocket(port);

		Thread thread = new Thread(new Runnable() {

			@Override
			public void run() {
				try {
					while (true) {
						clientDSocket.receive(receiveDP);
						// 读取udp报文内容
						String data = new String(receiveDP.getData());
						String[] info = data.split("@@", 6);

						System.out.println(receiveDP.getAddress() + " +  "
								+ receiveDP.getPort() + " " + data);

						String userip = info[0];
						int userport = Integer.parseInt(info[1]);
						String state = info[2];
						int userheadnum = Integer.parseInt(info[3]);
						String username = info[4];

						// 判断是否需要添加到UserList里，
						if (!UserList.userlist.containsKey(username)) {
							User user = new User();
							user.setUserHeadNum(userheadnum);
							// 此处因为电脑自动获取的ip可能有误，所以根据广播得到的ip作为用户的ip。
							user.setUserIP(receiveDP.getAddress().toString()
									.replace("/", ""));
							user.setUsername(username);
							user.setUserPort(userport);
							UserList.addUser(user);
							// 同时要在gui上加一个用户
							listmodel.addCell(user);
						}

						// 判断是否需要回复
						if (state.equals("0")) {
							System.out.println("UDP data state = 0,需要回复"
									+ receiveDP.getAddress().toString() + ":"
									+ receiveDP.getPort());
							sendMessage(userFormat(MyInfo.me, 1),
									receiveDP.getAddress(), receiveDP.getPort());
						} else {
							System.out.println("UDP data state = 1,不需要回复");
						}

					}
				} catch (IOException e) {
					e.printStackTrace();
				}

			}

		});
		thread.start();
	}

	/**
	 * 新建一个定时发送心跳消息的线程。每1s发送一个心跳。每10次心跳则刷新一次列表
	 * @param message 发送的消息
	 * @param listmodel list数据源
	 */
	public void heartBeatMessage(final String message,final UserListModel listmodel) {
		Thread thread = new Thread(new Runnable() {
			@Override
			public void run() {
				// 休眠1秒后发送消息，让gui能先跑起来
				try {
					Thread.sleep(1000);
					sendMessage(message);
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
				int i = 0;
				// 周期的心跳信号
				while (true) {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					i++;
					if(i==10){
					}
					sendMessage(message);
					
				}

			}

		});
		thread.start();
	}
	/**
	 * 将user信息格式化成String对象。
	 * @param user
	 * @param state 是否需要回复
	 * @return 
	 */
	public static String userFormat(User user, int state) {
		return user.getUserIP() + "@@" + user.getUserPort() + "@@" + state
				+ "@@" + user.getUserHeadNum() + "@@" + user.getUsername()
				+ "@@end";
	}

}
